<?php

namespace common\jobs\handle;

use Yii;
use yii\db\Exception;
use common\models\cms\CmsSpecial;
use common\models\uvs\UvsScene;
use common\models\uvs\UvsTask;
use common\models\uvs\UvsUserTask;
use common\models\uvs\UvsUserExpLog;
use common\models\uvs\UvsUserAccount;
use common\models\uvs\UvsLevel;
use common\models\cms\CmsWatchLog;
use yii\db\Expression;
use common\models\uvs\UvsUserRewardLog;
use common\models\game\GameUserChance;

/**
 * 专题经验任务处理
 *
 * @author emhome <emhome@163.com>
 * @since 1.0
 */
class SpecialUvsExpRewardHandle_1 extends \common\jobs\base\BaseJobHandleModel {

    /**
     * @var integer 专题ID
     */
    public $special_id = null;

    /**
     * @var integer 用户ID
     */
    public $user_id = null;

    /**
     * @var CmsSpecial|null 模型
     */
    private $_special = null;

    /**
     * @var UvsScene|null 模型
     */
    private $_scene = null;

    /**
     * @var CmsWatchLog[]|array 模型
     */
    private $_logs = [];

    /**
     * {@inheritdoc}
     */
    public function rules() {
        return [
            [['special_id', 'user_id'], 'required'],
            [['special_id', 'user_id'], 'integer'],
            [['special_id'], 'validateSpecial'],
            [['user_id'], 'validateUser'],
        ];
    }

    /**
     * 校验奖励日志信息
     * @param string $attribute the attribute currently being validated
     */
    public function validateSpecial($attribute) {
        if ($this->hasErrors()) {
            return;
        }
        $specialId = $this->$attribute;
        $special = CmsSpecial::find()->active(CmsSpecial::STATUS_ACTIVE)->andWhere([
            'id' => $specialId,
        ])->one();
        if (!$special) {
            return $this->addError($attribute, '【' . $specialId . '】专题不存在！');
        }
        $this->_special = $special;
        $scene = UvsScene::find()->active(UvsScene::STATUS_ACTIVE)->andWhere([
            'usage' => UvsScene::USAGE_SPECIAL,
            'usage_id' => $specialId,
        ])->one();
        if (!$scene) {
            return $this->addError($attribute, '【' . $specialId . '】专题经验场景不存在！');
        }
        $this->_scene = $scene;
    }

    /**
     * 校验奖励日志信息
     * @param string $attribute the attribute currently being validated
     */
    public function validateUser($attribute) {
        if ($this->hasErrors()) {
            return;
        }
        $uid = $this->$attribute;
        $query = CmsWatchLog::find()->active(CmsWatchLog::STATUS_DEFAULT)->andWhere([
            'user_id' => $uid,
            'special_id' => $this->special_id,
        ])->andWhere([
            '>', 'duration', new Expression('total'),
        ]);
        $logs = $query->all();
        if ($uid == 1063560) {
//            $query->debug();
//            Yii::error([
//                'hasLogs' => empty($logs),
//            ]);
        }
        if (empty($logs)) {
            return $this->addError($attribute, '【' . $uid . '】成长日志不符合条件！');
        }
        $this->_logs = $logs;
    }

    /**
     * 获取专题信息
     * @return CmsSpecial
     */
    public function getSpecial() {
        return $this->_special;
    }

    /**
     * 获取专题闯关场景信息
     * @return Game|null
     */
    public function getGame() {
        $special = $this->getSpecial();
        if (!$special) {
            return null;
        }
        return $special->game;
    }

    /**
     * 获取专题闯关场景信息
     * @return UvsScene|null
     */
    public function getGameScene() {
        $special = $this->getSpecial();
        if (!$special || !$special->game) {
            return null;
        }
        return $special->game->uvsScene;
    }

    /**
     * 获取场景信息
     * @return UvsScene
     */
    public function getScene() {
        return $this->_scene;
    }

    /**
     * 获取日志信息
     * @return CmsWatchLog[]
     */
    public function getLogs() {
        return $this->_logs;
    }

    /**
     * @inheritdoc
     */
    public function save() {
        if (!$this->validate()) {
            return $this->dumpError('检验失败');
        }
        //开启事务
        $transaction = Yii::$app->db->beginTransaction();
        try {
            $this->reward();
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            Yii::error($e->getMessage());
            return $this->dumpError($e->getMessage());
        }
        return $this->dumpSuccess([
            'RewardUserId' => $this->user_id,
            'Message' => '发放完成！',
        ]);
    }

    /**
     * 执行奖励计划
     * @inheritdoc
     */
    protected function reward() {
        //获取基础信息
        $scene = $this->getScene();
        $watchLogs = $this->getLogs();
        //闯关场景任务
        $gameScene = $this->getGameScene();
        /* @var $tasks UvsTask[] */
        $tasks = [];
        if ($gameScene) {
            $tasks = $gameScene->tasks;
        }
        //学习经验成长
        $expLog = new UvsUserExpLog();
        $expLog->setAttributes([
            'user_id' => $this->user_id,
            'scene_id' => $scene->id,
            'source' => UvsUserExpLog::SOURCE_CMS_WATCH_LOG,
            'status' => UvsUserExpLog::STATUS_ACTIVE,
        ]);
        //记录时长任务
        $watchVideoDuration = 0;
        $watchAudioDuration = 0;
        $watchArticles = [];
        foreach ($watchLogs as $log) {
            $duration = $log->duration - $log->total;
            if ($log->date == date('Y-m-d')) {
                if ($log->model == CmsWatchLog::MODEL_ARTICLE) {
                    $watchArticles[] = $log->model_id;
                } elseif ($log->model == CmsWatchLog::MODEL_VIDEO) {
                    $watchVideoDuration += $log->duration;
                } elseif ($log->model == CmsWatchLog::MODEL_AUDIO) {
                    $watchAudioDuration += $log->duration;
                }
            }
            if ($duration <= 0) {
                continue;
            }
            if ($log->model !== CmsWatchLog::MODEL_ARTICLE) {
                $_expLog = clone $expLog;
                $_expLog->source_id = $log->id;
                $_expLog->value = $duration;
                if (!$_expLog->save()) {
                    throw new Exception($_expLog->getErrorMsg());
                }
            }
            $log->total += $duration;
            if (!$log->save()) {
                throw new Exception($log->getErrorMsg());
            }
        }
        $watchArticleNums = count(array_unique($watchArticles));


        //更新用户账户经验等级
        //统计用户经验值
        $exps = (int) UvsUserExpLog::find()->active(UvsUserExpLog::STATUS_ACTIVE)->andWhere([
            'user_id' => $this->user_id,
            'scene_id' => $scene->id,
        ])->sum('value');

        //根据经验值获取等级
        $achieveLevel = UvsLevel::findAchieveByValue($scene->id, $exps);

        //更新账户经验
        $userAccount = UvsUserAccount::findOrNew([
            'user_id' => $this->user_id,
            'scene_id' => $scene->id,
        ]);
        if ($userAccount->isNewRecord) {
            $userAccount->status = UvsUserAccount::STATUS_ACTIVE;
        }
        //冻结账户直接返回false结束奖励
        if ($userAccount->status != UvsUserAccount::STATUS_ACTIVE) {
            return false;
        }
        if ($achieveLevel) {
            $userAccount->level = $achieveLevel->text;
            $userAccount->level_id = $achieveLevel->id;
        }
        $userAccount->exp = $exps;
        if (!$userAccount->save()) {
            throw new Exception($userAccount->getErrorMsg());
        }
        //记录任务日志
        $taskLog = new UvsUserTask();
        $taskLog->setAttributes([
            'user_id' => $this->user_id,
            'date' => date('Y-m-d'),
            'times' => 1,
            'status' => UvsUserTask::STATUS_ACTIVE,
        ]);
        
        if ($this->user_id == 1063560) {
            Yii::error([
                'watchVideoDuration' => $watchVideoDuration,
                'watchAudioDuration' => $watchAudioDuration,
                'watchArticleNums' => $watchArticleNums,
            ]);
        }
        foreach ($tasks as $task) {
            $conditionValue = 0;
            if ($task->unique_name == 'audio') {
                $conditionValue = $watchAudioDuration;
            } elseif ($task->unique_name == 'video') {
                $conditionValue = $watchVideoDuration;
            } elseif ($task->unique_name == 'article') {
                $conditionValue = $watchArticleNums;
            }

            if (!$conditionValue || $task->condition > $conditionValue) {
                continue;
            }

            //是否需要记录日志
            $needRecord = $task->getNeedRecord($this->user_id);

            if (!$needRecord) {
                continue;
            }
            //完成任务记录日志
            $_taskLog = clone $taskLog;
            $_taskLog->scene_id = $task->scene_id;
            $_taskLog->task_id = $task->id;
            if (!$_taskLog->save()) {
                throw new Exception($_taskLog->getErrorMsg());
            }
            //是否有奖品
            $prizes = $task->prizes;
            if (empty($prizes)) {
                continue;
            }
            //派奖记录奖励日志
            $rewardLog = new UvsUserRewardLog();
            $rewardLog->setAttributes([
                'user_id' => $this->user_id,
                'scene_id' => $task->scene_id,
                'source' => UvsUserRewardLog::SOURCE_TASK,
                'source_id' => $_taskLog->id,
                'prize_id' => 'Prize ID',
                'prize_value' => 'Prize Value',
                'status' => UvsUserRewardLog::STATUS_ACTIVE,
            ]);

            $gameChance = new GameUserChance();
            $gameChance->setAttributes([
                'game_id' => $gameScene->usage_id,
                'user_id' => $this->user_id,
                'date' => date('Y-m-d'),
                'from' => GameUserChance::FROM_UVS_REWARD,
                'used_times' => 0,
                'lock_times' => 0,
                'locked_at' => 0,
                'expired_at' => 0,
                'status' => GameUserChance::STATUS_ACTIVE,
            ]);
            foreach ($prizes as $prize) {
                if ($prize->stocks <= 0) {
                    continue;
                }
                $_rewardLog = clone $rewardLog;
                $_rewardLog->prize_id = $prize->id;
                $_rewardLog->prize_value = $prize->value;
                if (!$_rewardLog->save()) {
                    throw new Exception($_rewardLog->getErrorMsg());
                }
                if ($prize->type != $prize::TYPE_GAME_CHANCE) {
                    continue;
                }
                //触发扩展奖励
                $_gameChance = clone $gameChance;
                $_gameChance->times = $prize->value;
                $_gameChance->from_id = $_rewardLog->id;
                if (!$_gameChance->save()) {
                    throw new Exception($_gameChance->getErrorMsg());
                }
            }
        }
    }

}
